Skip to content

Plugin format for skills + local NuGet flow + agent kit#225

Merged
codemonkeychris merged 6 commits into
mainfrom
skills-plugin-format
May 9, 2026
Merged

Plugin format for skills + local NuGet flow + agent kit#225
codemonkeychris merged 6 commits into
mainfrom
skills-plugin-format

Conversation

@codemonkeychris
Copy link
Copy Markdown
Collaborator

@codemonkeychris codemonkeychris commented May 9, 2026

Summary

  • Plugin-format skills. Restructures the agent-facing docs around the Copilot CLI / Claude plugin layout (plugins/reactor/{plugin.json, agents/, skills/<name>/SKILL.md}) so the SDK's native skill-loading subsystem fires skill.invoked instead of agents treating SKILL.md as an ordinary file. Eval feedback flagged this as the biggest single lever (~−28% tokens, −48% cost on the win-dev-skills calculator comparison).
  • Local NuGet flow. mur pack-local packs the framework and project-templates into <repo>/local-nupkgs/, so selfhost devs and NuGet consumers use the same #:package Microsoft.UI.Reactor@0.0.0-local reference and dotnet new reactorapp resolves through the same feed. Repo-level nuget.config wires it up.
  • Agent kit in the NuGet. Packs the plugin tree + legacy SKILL.md + skills + recipes + signatures index into the framework NuGet at agentkit/, so consumers get the same context as selfhost via dotnet restore.
  • mur check for one-line build diagnostics with skill-file pointers, and the MissingWithKeyAnalyzer (REACTOR_DSL_001) — the highest-cited gotcha the compiler doesn't catch.

What's in plugins/reactor/

Skill When loaded Content
reactor-getting-started always (agent preload) minimal single-file #:package starter, .csproj template, hooks table, common factories, React→Reactor mapping, theme tokens, critical gotchas, mode detection (selfhost vs. consumer)
reactor-dsl only when verifying a less-common signature pointer to references/reactor.api.txt — the full alphabetized signatures index (~12K tokens)
reactor-build-and-check on demand mur check usage, common-build-errors cheat table mapping REACTOR_* / CS* IDs to one-line fixes
reactor-{async,design,forms,navigation,input,charts,commanding,devtools} on demand migrated from skills/<name>.md with plugin-format frontmatter
reactor-recipes on demand paste-ready single-file recipes in references/

Loading order is preload-light: only reactor-getting-started is preloaded, and the rest fire on demand from frontmatter description keyword match. The legacy single-file SKILL.md + skills/ tree are preserved for environments that don't support plugin loading.

Commits in this PR

Commit Purpose
e983eec Plugin format for skills + local NuGet flow + agent kit (initial drop)
ac7c522 CI: skip SignaturesGen AfterBuild exec when target arch ≠ host arch (fixes MSB3073 exit 216 on the x64 GitHub runner)
af62739 Skill: rephrase plugin-vs-fallback guidance
3859e08 Review: address Copilot CR feedback (7 findings — async stream draining, WrapPanel→WrapGrid, recipe index wording, Pending mention, --regen-api Platform, dual-write generator)
d328411 mur pack-local also packs the project-templates nupkg into local-nupkgs/ and prints dotnet new install/reactorapp commands
4b51cea Skills: move 90% of DSL content into reactor-getting-started, slim reactor-dsl to a pointer at the api index

dotnet new reactorapp flow (new)

# One-time bootstrap (inside the clone):
.\bin\<arch>\mur.exe pack-local                            # packs framework + templates into local-nupkgs/
dotnet new install (Resolve-Path local-nupkgs\Microsoft.UI.Reactor.ProjectTemplates.0.0.0-local.nupkg)

# Create:
dotnet new reactorapp -n MyApp                             # restores Microsoft.UI.Reactor 0.0.0-local through the feed

For evals or workspaces outside the clone, drop a workspace-local nuget.config with an absolute path to <repo>/local-nupkgs/ (the in-repo nuget.config uses a relative path that only resolves when CWD is inside the clone).

Eval-harness notes

  • Skill resolution points at plugins/reactor/ (or <package-cache>/agentkit/plugins/reactor/).
  • Prior eval had 0 skill.invoked events — with this layout, expect ≥2 per run.
  • mur is not yet shipped as a global dotnet tool — lives at <repo>/bin/<arch>/mur.exe after building Reactor.Cli. Skill guidance prefers the loaded plugin over mur --skill / cache-map file reads (those are only fallbacks).
  • A full eval set is being run against this branch — results will land as a PR comment.

Test plan

  • dotnet build Reactor.slnx --configuration Release (CI build-solution job — green)
  • dotnet test tests/Reactor.Tests (unit tests — green)
  • dotnet test tests/Reactor.SelfTests (selftests — green)
  • Pack flow on windows-x64 CI runner (cross-arch SignaturesGen apphost no longer breaks the build)
  • mur pack-local produces both Microsoft.UI.Reactor.0.0.0-local.nupkg and Microsoft.UI.Reactor.ProjectTemplates.0.0.0-local.nupkg with the full agentkit/plugins/reactor/ tree
  • dotnet new install of the templates nupkg + dotnet new reactorapp -n MyApp restores cleanly through the local feed
  • mur check <path> emits REACTOR_DSL_001 diagnostic with skill pointer when .WithKey is missing
  • Eval run on the new skill layout (in flight — comment to follow)

Restructures the agent-facing skills around the Copilot CLI / Claude
plugin layout (plugins/reactor/{plugin.json, agents/, skills/<name>/SKILL.md})
so the SDK's native skill-loading subsystem fires `skill.invoked` instead
of the agent treating SKILL.md as an ordinary file. Each topical skill
gets a focused SKILL.md with keyword-rich frontmatter; deeper content
lives under references/.

New skills (under plugins/reactor/skills/):
- reactor-getting-started — minimal single-file `#:package` starter, .csproj
  template, mode detection, package consumption, cache map fallback
- reactor-dsl — DSL essentials, hooks, components, theme tokens, gotchas;
  references/reactor.api.txt is the full alphabetized signatures index
- reactor-build-and-check — `mur check` usage, common-build-errors cheat
  table mapping REACTOR_* / CS* IDs to one-line fixes
- reactor-{async,design,forms,navigation,input,charts,commanding,devtools}
  — migrated from skills/<name>.md with plugin-format frontmatter
- reactor-recipes — paste-ready single-file recipes in references/

Local NuGet flow + agent kit:
- tools/Reactor.SignaturesGen — reflection-based generator emitting
  skills/reactor.api.txt from the built Reactor.dll. AfterBuild target
  skips when RuntimeIdentifier is set so cross-arch publishes don't fail.
- nuget.config + local-nupkgs/ — repo-level local feed
- mur pack-local — packs Microsoft.UI.Reactor.0.0.0-local.nupkg into the
  feed and clears NuGet's HTTP cache
- mur api / --regen-api — print / regenerate the signatures index
- mur check — runs `dotnet build` and emits one-line diagnostics with
  skill-file pointers for known REACTOR_* analyzer IDs
- Reactor.csproj packs the full plugin tree into agentkit/plugins/reactor/
  alongside the legacy SKILL.md + skills/ + reactor.api.txt

New analyzer:
- REACTOR_DSL_001 (MissingWithKeyAnalyzer) — flags Select(...) into a
  layout container without .WithKey on items

Recipes (skills/recipes/):
- async-fetch-list, form-with-validation, list-add-delete, sidebar-nav,
  themed-card — all compile against the local feed; verified end-to-end
  via c:\temp\nuget-test*.

Root SKILL.md is preserved as a fallback for environments without plugin
loading and now leads with a pointer to the plugin path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reorganizes Reactor’s agent-facing documentation into a plugin-based skill layout, adds a local NuGet packing workflow for selfhost development, and introduces tooling/analyzers to reduce agent token usage and improve fast diagnostics.

Changes:

  • Add plugins/reactor/ plugin format (agents + per-skill docs + recipe references) and pack the full “agent kit” into the Microsoft.UI.Reactor NuGet under agentkit/.
  • Introduce mur pack-local and repo-level nuget.config to enable a consistent local-feed workflow (0.0.0-local).
  • Add mur check for one-line diagnostics + a new analyzer REACTOR_DSL_001 to detect missing .WithKey(...) in common dynamic-list patterns, plus a signatures generator (reactor.api.txt).
Show a summary per file
File Description
tools/Reactor.SignaturesGen/Reactor.SignaturesGen.csproj New tool project to reflect over Reactor and emit the API signatures index.
tools/Reactor.SignaturesGen/Program.cs Implements API index generation (factories/modifiers/hooks/theme/enums).
src/Reactor/Reactor.csproj Packs agent kit (legacy skills + plugin tree + signatures index) into the Reactor NuGet.
src/Reactor.Cli/Reactor.Cli.csproj Embeds reactor.api.txt into mur and adds build-order dependency on signatures generator.
src/Reactor.Cli/Program.cs Adds --api, --regen-api, check, and pack-local CLI entry points.
src/Reactor.Cli/Pack/PackLocalCommand.cs Implements mur pack-local to pack a local 0.0.0-local nupkg into local-nupkgs/.
src/Reactor.Cli/Check/CheckCommand.cs Implements mur check wrapper around dotnet build with structured one-line diagnostics + hints.
src/Reactor.Analyzers/MissingWithKeyAnalyzer.cs Adds REACTOR_DSL_001 analyzer for missing .WithKey(...) in dynamic list projections.
src/Reactor.Analyzers/AnalyzerReleases.Unshipped.md Registers the new analyzer ID in release notes.
skills/recipes/themed-card.cs New legacy recipe demonstrating themed card surface.
skills/recipes/sidebar-nav.cs New legacy recipe demonstrating NavigationView + UseNavigation.
skills/recipes/list-add-delete.cs New legacy recipe demonstrating keyed dynamic list + reducer updates.
skills/recipes/index.md New legacy recipes index (intent → recipe map).
skills/recipes/form-with-validation.cs New legacy recipe for validation context + FormField.
skills/recipes/async-fetch-list.cs New legacy recipe for UseResource async loading/data/error states.
skills/reactor.api.txt Generated legacy signatures index committed to repo.
SKILL.md Updates legacy monolithic skill to point to plugin format + local NuGet flow + new CLI commands.
Reactor.slnx Adds the new signatures generator tool project to the solution.
plugins/reactor/plugin.json Adds plugin manifest for plugin-based skill loading.
plugins/reactor/.claude-plugin/plugin.json Adds Claude plugin manifest for the same plugin content.
plugins/reactor/agents/reactor-dev.agent.md Defines reactor-dev agent instructions and skill-loading guidance.
plugins/reactor/skills/reactor-getting-started/SKILL.md Plugin skill: setup/bootstrap + selfhost vs consumer guidance.
plugins/reactor/skills/reactor-dsl/SKILL.md Plugin skill: DSL essentials + gotchas + pointer to signatures index.
plugins/reactor/skills/reactor-dsl/references/reactor.api.txt Plugin copy of the generated signatures index for efficient lookup.
plugins/reactor/skills/reactor-build-and-check/SKILL.md Plugin skill: build/check workflow + common diagnostics cheat table.
plugins/reactor/skills/reactor-async/SKILL.md Plugin skill: async hooks (UseResource/UseMutation/UseInfiniteResource).
plugins/reactor/skills/reactor-forms/SKILL.md Plugin skill: controlled inputs + validation + FormField patterns.
plugins/reactor/skills/reactor-navigation/SKILL.md Plugin skill: navigation model and common patterns (sidebar, tabs, deep links).
plugins/reactor/skills/reactor-input/SKILL.md Plugin skill: pointer/gesture APIs, focus management, drag/drop.
plugins/reactor/skills/reactor-charts/SKILL.md Plugin skill: charting guidance and DSL usage.
plugins/reactor/skills/reactor-commanding/SKILL.md Plugin skill: commands/accelerators/UseCommand guidance.
plugins/reactor/skills/reactor-devtools/SKILL.md Plugin skill: mur devtools usage and workflows.
plugins/reactor/skills/reactor-recipes/SKILL.md Plugin skill: recipe index and usage contract.
plugins/reactor/skills/reactor-recipes/references/themed-card.cs Plugin recipe reference: themed card.
plugins/reactor/skills/reactor-recipes/references/sidebar-nav.cs Plugin recipe reference: sidebar navigation.
plugins/reactor/skills/reactor-recipes/references/list-add-delete.cs Plugin recipe reference: list add/toggle/delete with keys.
plugins/reactor/skills/reactor-recipes/references/index.md Plugin recipes index.
plugins/reactor/skills/reactor-recipes/references/form-with-validation.cs Plugin recipe reference: form validation.
plugins/reactor/skills/reactor-recipes/references/async-fetch-list.cs Plugin recipe reference: async fetch list.
nuget.config Adds repo-level local feed source (local-nupkgs) plus nuget.org.
local-nupkgs/.gitignore Prevents committing locally packed nupkgs/snupkgs.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 42/42 changed files
  • Comments generated: 7

Comment thread src/Reactor.Cli/Check/CheckCommand.cs
Comment thread src/Reactor.Analyzers/MissingWithKeyAnalyzer.cs
Comment thread skills/recipes/index.md Outdated
Comment thread plugins/reactor/skills/reactor-recipes/references/index.md Outdated
Comment thread plugins/reactor/skills/reactor-recipes/SKILL.md Outdated
Comment thread src/Reactor.Cli/Program.cs
Comment thread tools/Reactor.SignaturesGen/Program.cs
codemonkeychris and others added 3 commits May 9, 2026 09:46
CI was failing on `dotnet build Reactor.slnx` (windows-latest, x64 host)
because the slnx defaults Platform=ARM64 for projects that opt in. The
AfterBuild target then runs `Reactor.SignaturesGen.exe` — an ARM64 apphost
the x64 host cannot execute, exiting with code 216 ("not compatible with
the version of Windows you're running") and producing MSB3073.

The previous skip-condition only checked RuntimeIdentifier; this path
sets only Platform. Now resolve target arch from Platform/RID and host
arch from \$(NETCoreSdkRuntimeIdentifier), and skip regen when they differ.
The committed skills/reactor.api.txt is still picked up by pack.

Verified locally on win-arm64:
  -p:Platform=ARM64  → regen runs (target=arm64, host=arm64)
  -p:Platform=x64    → regen skipped (target=x64,  host=arm64)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reframe the bootstrap step as imperatives ("Load the skill") rather than
"these two skills" so the agent treats them as actions. Make the
fallback path explicit (mur --skill / --api / cache-map reads) with
the cost rationale spelled out.
- mur check: drain stdout/stderr concurrently to avoid pipe-buffer
  deadlock on noisy `dotnet build` output
- MissingWithKeyAnalyzer: fix layout-factory list — `WrapPanel` is not a
  Reactor factory; use `WrapGrid`. Drop `ScrollView` (single-child, not
  Element[]).
- Recipes index (both legacy and plugin copies): wording said
  `#:project ../../src/Reactor` but the recipes use
  `#:package Microsoft.UI.Reactor@0.0.0-local`. Align to the local-feed
  flow.
- reactor-recipes skill / recipe indices: drop `Pending` from the
  async-fetch row — the recipe uses `UseResource` + `AsyncValue<T>.Match`
  and never references `Pending`.
- mur --regen-api: pass `-p:Platform=<host arch>` to match check /
  pack-local; WinUI projects require an explicit Platform.
- SignaturesGen: write to both `skills/reactor.api.txt` (legacy /
  agentkit) and `plugins/reactor/skills/reactor-dsl/references/
  reactor.api.txt` (plugin path). Single source of truth — the two
  committed copies stay in sync.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codemonkeychris codemonkeychris marked this pull request as ready for review May 9, 2026 17:45
codemonkeychris and others added 2 commits May 9, 2026 14:23
`dotnet new reactorapp` requires both the framework nupkg and the
project-templates nupkg. Previously only the framework was packed; the
templates package was emitted only to tools/Templates/bin/Release/ as a
side effect of GeneratePackageOnBuild, leaving evals and dev workflows
to discover an undocumented path.

Now `mur pack-local` produces both packages in <repo>/local-nupkgs/ and
prints the dotnet-new install + create commands at the end. Includes a
note that consumers outside the clone need an absolute-path nuget.config
or a global feed registration, since the in-repo nuget.config uses a
relative path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move the 90% DSL content into reactor-getting-started so most tasks need
a single skill load. Slim reactor-dsl to a pointer at the full
references/reactor.api.txt index (loaded only when a less-common
signature needs verification). Update reactor-dev process guidance to
emphasize batch edits, a final build (not per-file rebuilds), and
React-shaped intuition with C# spelling.
@codemonkeychris
Copy link
Copy Markdown
Collaborator Author

Eval results — first iteration of 5x batch on this branch

Model: gpt-5.5. Same harness, prompts, and specs as the prior PROGRESS baselines.

reactor-calc — vs the original "first runs"

Phase 1 naive (in-cwd skill.md, gpt-5.5) Phase 2 5-mean (skill loaded as a file) this branch + dotnet new reactorapp Δ vs Phase 1 Δ vs Phase 2
wall 518 s 290.8 s 197 s −62% −32%
turns 17 15.6 11 −35% −29%
total tokens 661,259 497,867 390,276 −41% −22%
cost (USD) $5.10 $4.68 $3.30 −35% −29%
first build (n/a) (n/a) ok

reactor-kanban — gap to WinUI XAML

The kanban scenario was added after Phase 5; the closest pre-template baseline I have is the post-plugin / pre-dotnet new reactorapp run from earlier today. Tokens are model-independent so they're the cleanest comparison; wall time is mixed model+skill effect.

pre-template baseline this branch + template + React-anchor + pointer-table Δ
wall 1131 s (sonnet-4.6) 430 s (gpt-5.5) mixed
turns 21 15 −29%
total tokens 1,582,023 756,208 −52%
tools / turn 1.10 2.40 (batching directive working)
first build ok ok ✓

Side-by-side with winui-xaml-kanban (same harness, same model)

reactor-kanban winui-xaml-kanban reactor / winui
wall 430 s 495 s 0.87× ✓ reactor faster
turns 15 13 1.15×
tools / turn 2.40 2.00 reactor batches tighter
total tokens 756,208 556,073 1.36×
cost (USD) $4.50 $3.90 1.15×
LoC (agent) 305 598 0.51× (DSL is denser)

The pre-PR ratio was 1.86× (reactor / winui tokens) on the kanban scenario. After this branch's changes, it's 1.36× — that closes ~58% of the gap.

What moved the numbers (in order of impact, from event-log diagnostics)

  1. dotnet new reactorapp template + the local-feed setup wiring (this PR's d328411). The single biggest structural lever — replaces ~7 file-create turns with one powershell invocation. This alone took the post-plugin reactor-kanban run from 504 s → 270 s in isolation.
  2. Plugin-format skills (e983eec). Eliminates the +30 K mid-session conversation injection that pre-plugin runs paid back across 16+ subsequent turns. Confirmed on event traces: pre-plugin step-6 conversation jumps +32 K; post-plugin it's ~+5 K.
  3. reactor-getting-started rewrite (4b51cea + follow-on). Moved the React→Reactor mapping to the top, absorbed hooks/factories/gotchas, slimmed reactor-dsl to a pointer at references/reactor.api.txt.
  4. Agent.md edit. Directs the agent to scaffold via dotnet new reactorapp first, then batch its file-creates and build at the end (not after every file). The "build at the end" line lifted tools/turn from 1.10 to 1.55–2.40 across runs.

Things tried that didn't pay off

  • Inline paste-ready code samples (drag/drop, ContentDialog, flyout, context provider) embedded in the skill regressed turns by ~10% and tokens by ~4%. The agent saw the samples as a feature menu and generated more code. Replaced with a pointer table ("for X see samples/.../Y.cs") at ~1/30th the always-loaded token cost — that recovered the regression.

Caveats

  • This is iter 1 of 5. Reactor wall-time CV from prior batches ran 13–40 %. Need the full batch to confirm these aren't favorable singletons.
  • The wall-time advantage over WinUI may be specific to this iter / model. The token ratio (1.36×) is the more stable claim.
  • The remaining 36 % token gap is mostly the agent's reactor.api.txt ripgrep lookups (~12 calls @ ~3 K each in this run) — WinUI needs ~zero signature confirmations because XAML/MVVM is saturated in training data. Open lever for follow-on work: a structured mur api lookup <symbol> tool, or richer always-loaded snippets for the most-grepped patterns.

Full per-iter table + variance stats will follow once the 5x batch completes.

@codemonkeychris codemonkeychris merged commit f34924e into main May 9, 2026
6 checks passed
@codemonkeychris codemonkeychris deleted the skills-plugin-format branch May 9, 2026 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants